home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / Sample Code / Graphics Samples / 3 circles - hit testing ƒ / 3 circles - hit testing.c next >
Encoding:
C/C++ Source or Header  |  1996-04-14  |  11.1 KB  |  334 lines  |  [TEXT/KAHL]

  1. /*
  2.     3 Circles - Hit Test
  3.     
  4.     This application creates three circles on top of a black rectangle the size of the portRect of the window. Each circle is
  5.     colored in an RGB color with a the "addMode" transfer mode.  The user will be able to select one of the circles and drag 
  6.     it around the window. Anytime, one of the circles intersects another, the transfer mode of both circles will be applied 
  7.     to the intersection of the two shapes, thereby creating a new color when the shapes are redrawn.  I use the QuickDraw 
  8.     GX offscreen library to produce flicker free double buffering  of the shapes within the window. You will see a little 
  9.     flicker when you are running the "debugging" version of the GXGraphics(debug) init. It looks really nice with 
  10.     non-debugging init.
  11.  
  12.     Enjoy, 
  13.     
  14.     ...Luke
  15.     
  16.     >> Pete "Luke" Alexander
  17.     >> Developer Technical Support
  18.     
  19.     KNOWN BUGS:
  20.     1) If you drag the window to a monitor which is not in color, some of the circles will disappear. In some cases, this is
  21.     the correct behavior, but in others it is not. 
  22.     
  23.     2) If drag the window to span across two different depth monitors, all of the 
  24.     
  25.     NOTES:
  26.     • This file requires the following files to run correctly:
  27.         "graphics shell.c", "ColorLibrary.c", "GraphicsDebugLibrary.c", "OffscreenLibrary.c", "OvalLibrary.c", 
  28.          "PictureLibrary.c","QDLibrary.c", "ShapeLibrary.c", "TransferModeLibrary.c", "TransformLibrary.c".
  29.         
  30.     • This file prints the "best" in landscape mode.
  31.     
  32.     ©1990 -1996 Apple Computer, Inc.
  33.     All rights reserved.
  34.  
  35.     Change History:
  36.  
  37.        4/96    bob        Updated the above "NOTES", and copyright date.
  38.                     Updated #includes to support changed GX Library names.
  39.  
  40. */
  41.  
  42.  
  43.  
  44. #include <Events.h>
  45. #include <Windows.h>
  46. #include <Quickdraw.h>
  47.  
  48. #include <GXGraphics.h>
  49. #include <GXEnvironment.h>
  50. #include "GraphicsLibraries.h"
  51. #include "QDLibrary.h"
  52. #include "OffscreenLibrary.h"
  53.  
  54. #include "graphics shell.h"
  55.  
  56. #define    kWinWidth        400        /* The window width. */
  57. #define    kWinHeight    400        /* The window height. */
  58.  
  59. #define useOffScreen
  60.  
  61. //
  62. //  Set up the title and size of the window 
  63. //
  64. Rect        gWindowQDRect = {40, 10, kWinWidth, kWinHeight};
  65. Str255     gWindowTitle = "\pClick and drag a circle...";
  66.  
  67.  
  68. //
  69. //    gGraphicsHeapSize sets the size of the graphics heap created by calling the NewGraphicsClient routine
  70. //    in main () within graphics shell.c.  You can determine the amount of graphics heap required by using GraphicsBug.
  71. //    With  gGraphicsHeapSize set to 25k, I had 2 free blocks left in the graphics heap. Sounds good to me.
  72. //
  73. long        gGraphicsHeapSize = 375;
  74.  
  75.  
  76. gxShape                 gThePicture;
  77. offscreen                 gAnimationWorld, gAnimationWorldBackGround;  /* Off-screen bit map for marquee animation */
  78. extern gxViewPort        gTheWindowsViewPort;    
  79.  
  80.  
  81.  
  82. /*------ DoInitialization ---------------------------------------------------------------------------------
  83. **
  84. **    Create the background rectangle and the 3 circles.
  85. */
  86. void DoInitialization(theWindow)
  87. WindowPtr theWindow;
  88. {
  89.     gxShape        myCircle, tempCircleShape;
  90.     gxRectangle    circleGeometry = {ff(15), ff(15), ff(115), ff(115)};
  91.     gxShape         backBits, baseBits,
  92.                 theBackground;                    // Off-screen bitmap to use as base for off-screen bitmap
  93.     gxBitmap        baseMap;                         // Bitmap to use as base for off-screen drawing environment 
  94.     gxPoint         mapPos;                          // Position of the bit map 
  95.     gxColor        rgbColor;
  96.     Rect            windowRect;
  97.     CTabHandle     standardClut;
  98.     gxColorSet    setOfColors;
  99.     gxTransform     savedTransform;              // Transform from gAnimationWorldBackGround bit map shape 
  100.     
  101.     //
  102.     //     Create a picture which will contain the 3 circles and the back background rectangle. We will be adding a 
  103.     //    unique copy of each circle to our picture - "gThePicture" by calling GXSetPictureParts below.
  104.     //
  105.     gThePicture = GXNewShape( gxPictureType );
  106.  
  107.     //
  108.     //    Create the black background rectangle and add it to our picture - "gThePicture". We also set it's hit testing
  109.     //    information to prevent it from being moved (i.e. hit tested). Otherwise, the user could move our background.
  110.     //
  111.     SetShapeCommonColor ( gWindowBoundsShape, gxBlack );
  112.     GXSetShapeHitTest( gWindowBoundsShape, gxNoPart, 0 );
  113.     GXSetPictureParts( gThePicture, 0, 0, 1, &gWindowBoundsShape, nil, nil, nil );
  114.  
  115.     //
  116.     //    Create the three circles: with an RGB color and addMode transfer mode.
  117.     //
  118.     //    We create an RGB color space, and initially set to to red. We will update the color to be different color in RGB space.
  119.     //    The hit testing parameter for each circle is set to allow a user to "hit" the shape any time they click within the 
  120.     //    geometry of the shape. We will move each circle down the left side of the window.  After the circles has been created
  121.     //    and defined, the circle will be added to our GX picture - "gThePicture".
  122.     //
  123.     rgbColor.space                 = gxRGBSpace;
  124.     rgbColor.profile             = nil;
  125.     rgbColor.element.rgb.red         = 0xffff;    
  126.     rgbColor.element.rgb.green     = 0x0000;     
  127.     rgbColor.element.rgb.blue         = 0x0000;     
  128.  
  129.     //
  130.     // Create a red circle
  131.     //
  132.     myCircle = NewOval( &circleGeometry ); 
  133.     GXSetShapeColor( myCircle, &rgbColor );
  134.     SetShapeCommonTransfer( myCircle, gxAddMode );
  135.     GXSetShapeHitTest( myCircle, gxGeometryPart, ff(1) );
  136.     GXSetPictureParts( gThePicture, 0, 0, 1, &myCircle, nil, nil, nil );
  137.  
  138.     //
  139.     // Create a green circle
  140.     //
  141.     tempCircleShape = GXCopyToShape ( nil, myCircle );
  142.     GXDisposeShape( myCircle );  
  143.  
  144.     rgbColor.element.rgb.red         = 0x0000;    
  145.     rgbColor.element.rgb.green     = 0xffff;     
  146.     GXSetShapeColor( tempCircleShape, &rgbColor );
  147.     
  148.     GXMoveShape ( tempCircleShape, 0, ff(115) );
  149.     GXSetPictureParts( gThePicture, 0, 0, 1, &tempCircleShape, nil, nil, nil );
  150.  
  151.     //
  152.     // Create a blue circle
  153.     //
  154.     myCircle = GXCopyToShape ( nil, tempCircleShape );
  155.     GXDisposeShape( tempCircleShape );  
  156.  
  157.     rgbColor.element.rgb.green     = 0x0000;    
  158.     rgbColor.element.rgb.blue         = 0xffff;     
  159.     GXSetShapeColor( myCircle, &rgbColor );
  160.     
  161.     GXMoveShape ( myCircle, 0, ff(115) );
  162.     SetShapeCommonColor( myCircle, blue );
  163.     GXSetPictureParts( gThePicture, 0, 0, 1, &myCircle, nil, nil, nil );
  164.  
  165.     GXDisposeShape( myCircle );  
  166.     
  167.     //
  168.     //    Create a color set from the standard color table used by the system. This color set will be used
  169.     //    when we create the GX off screen worlds to make sure they contain the appropriate colors possible
  170.     //    when drawing to a window.
  171.     //
  172.     standardClut = GetCTable( 72 );
  173.     setOfColors = CTableToColorSet( standardClut );
  174.     DisposCTable( standardClut );
  175.  
  176.     // 
  177.     //    Set up the bitmap shape which will be used for our GX off-screen worlds...
  178.     //
  179.     windowRect = (*theWindow).portRect;
  180.     
  181.     baseMap.image        = nil;
  182.     baseMap.width         = windowRect.right - windowRect.left;
  183.     baseMap.height         = windowRect.bottom - windowRect.top;
  184.     baseMap.rowBytes     = 0;
  185.     baseMap.pixelSize     = 8;
  186.     baseMap.space         = gxIndexedSpace;
  187.     baseMap.set         = setOfColors;
  188.     baseMap.profile     = nil;
  189.     
  190.     mapPos.x     = mapPos.y = 0;
  191.     
  192.     //
  193.     //    Create 2 GX off screen worlds: one for the background contents of the window (named: gAnimationWorldBackGround)
  194.     //    and one for the drawing of the circle as the user drags one around the screen.
  195.     //    
  196.     baseBits = GXNewBitmap( &baseMap, &mapPos );
  197.     CreateOffscreen( &gAnimationWorld, baseBits );
  198.     GXDisposeShape( baseBits );
  199.     
  200.     baseBits = GXNewBitmap( &baseMap, &mapPos );
  201.     CreateOffscreen( &gAnimationWorldBackGround, baseBits );
  202.     GXDisposeShape( baseBits);
  203.     GXDisposeColorSet( setOfColors );
  204.         
  205.     //
  206.     //    Initialize the gAnimationWorldBackGround off screen to white. We accomplish this by creating a shape
  207.     //    containing a rectangle, set it's transform to the off screen world, and draw the shape by calling GXDrawShape.
  208.     //    The shape draws to the off screen world because the it's transform points to it
  209.     //
  210.     theBackground = GXCopyToShape ( nil, gWindowBoundsShape );
  211.  
  212.     SetShapeCommonColor ( theBackground, gxWhite );
  213.     GXSetShapeTransform( theBackground, gAnimationWorldBackGround.xform );
  214.     GXDrawShape ( theBackground );
  215.     GXDisposeShape( theBackground) ;  
  216.  
  217.     //
  218.     //    Set the transform of our gAnimationWorld off screen world same as our gAnimationWorldBackGround
  219.     //    off screen world.
  220.     //
  221.     savedTransform = GXGetShapeTransform( gAnimationWorldBackGround.draw );
  222.     GXSetShapeTransform( gAnimationWorldBackGround.draw, gAnimationWorld.xform );
  223. }
  224.  
  225.  
  226. /*------ DoClick ---------------------------------------------------------------------------------------*/
  227. void DoClick( orgMouseLoc, theWindow )
  228. gxPoint        orgMouseLoc;
  229. WindowPtr     theWindow;
  230. {
  231.     gxHitTestInfo     test;
  232.     gxShape        hit;
  233.  
  234.     GXIgnoreGraphicsNotice (transform_already_set);
  235.  
  236.     if ( GXHitTestPicture( gThePicture, &orgMouseLoc, &test, 1, 1 ) )
  237.     {
  238.         if ( StillDown() )
  239.         {           
  240.             gxShape    pageShape, tempShape;
  241.             gxPoint     newMouseLoc;
  242.             Point        currMouseLoc;
  243.                 
  244.                     //
  245.                     //    Get the shape hit by the user from the picture.
  246.                     //
  247.             hit = GetPictureItem( test.containerPicture, test.containerIndex, nil, nil, nil, nil );
  248.             GXSetShapeTransform( hit, gAnimationWorld.xform );
  249.  
  250.             //
  251.             //     Remove the hit shape from the picture and redraw it.
  252.             //
  253.             pageShape = GXCopyToShape ( nil,  test.containerPicture );
  254.             tempShape = ExtractShape( pageShape, test.containerIndex, 1 ); 
  255.             GXDisposeShape ( tempShape );
  256.             
  257.             GXSetShapeTransform( pageShape, gAnimationWorldBackGround.xform );
  258.             GXDrawShape ( pageShape );
  259.  
  260.  
  261.             while ( WaitMouseUp() ) 
  262.              {
  263.                  //
  264.                  //    Update the mouse location after the user has moved it. How? Get the mouse location from
  265.                  //    the Quickdraw based toolbox with the GetMouse function. We need to convert the QD point into a 
  266.                  //    fixed gxPoint, referring to the viewPort the mouse is located.
  267.                  //
  268.                  GetMouse( &currMouseLoc );
  269.                 LocalToGlobal( &currMouseLoc );
  270.                  GXConvertQDPoint( &currMouseLoc, gTheWindowsViewPort, &newMouseLoc );
  271.  
  272.                 //
  273.                 //    As the user drags a circle, we update the background of the window by drawing the contents
  274.                 //    of our GX off screen world containing the background of the window by calling
  275.                 //    GXDrawShape(gAnimationWorldBackGround.draw). We move the circle (i.e. hit) the user is dragging
  276.                 //    and redraw it. Finally, we update the contents of the window, thereby redrawing the area the
  277.                 //    user has messed up during the drag and update the location of the mouse.
  278.                 //
  279.                 if ( (newMouseLoc.x != orgMouseLoc.x) || (newMouseLoc.y != newMouseLoc.y))     // has the mouse moved??
  280.                  {
  281.                     GXDrawShape( gAnimationWorldBackGround.draw );
  282.  
  283.                      GXMoveShape ( hit, newMouseLoc.x - orgMouseLoc.x, newMouseLoc.y - orgMouseLoc.y );
  284.                     GXDrawShape( hit );
  285.  
  286.                      GXDrawShape( gAnimationWorld.draw );
  287.                  
  288.                      orgMouseLoc = newMouseLoc;
  289.                   }
  290.               
  291.              }
  292.              
  293.           GXDisposeShape ( pageShape );
  294.         }
  295.     }
  296.     GXPopGraphicsNotice ( );
  297. }
  298.  
  299.  
  300.  
  301. /*------ DoDraw ---------------------------------------------------------------------------------------*/
  302.  
  303. void DoDraw( theWindow )
  304.   WindowPtr theWindow;
  305. {
  306.     GXDrawShape( gThePicture );
  307. }
  308.  
  309.  
  310.  
  311. /*------ DoIdle -----------------------------------------------------------------------------------------*/
  312.  
  313. void DoIdle( theWindow )
  314. WindowPtr theWindow;
  315. {
  316. }
  317.  
  318.  
  319. /*------ DoDispose -------------------------------------------------------------------------------------*/
  320.  
  321. void DoDispose( theWindow )
  322. WindowPtr theWindow;
  323. {
  324.     DisposeCommonColors ( );
  325.     GXDisposeShape( gThePicture );
  326.     GXDisposeShape( gWindowBoundsShape );
  327.  
  328.     DisposeOffscreen( &gAnimationWorld );
  329.     DisposeOffscreen( &gAnimationWorldBackGround );
  330.     
  331.       DisposeWindow( theWindow );
  332. }
  333.  
  334.